/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-02-08     RT-Thread    the first version
 */
#ifndef __DRV_GPIO_H__
#define __DRV_GPIO_H__

/* IO default function */
#define IO_INPUT         (0x00)
#define IO_OUTPUT        (0x01)
#define IO_DISABLE       (0x07)

#define IO_FUN_2         (0x02)
#define IO_FUN_3         (0x03)
#define IO_FUN_4         (0x04)
#define IO_FUN_5         (0x05)
#define IO_FUN_6         (0x06)
#define IO_FUN_E         (0x0E)

/* IO port */
enum gpio_port
{
    GPIO_PORT_RESERVED0 = 0,
    GPIO_PORT_B,
    GPIO_PORT_C,
    GPIO_PORT_D,
    GPIO_PORT_E,
    GPIO_PORT_F,
    GPIO_PORT_G,
    GPIO_PORT_NUM,
};


enum gpio_drv_t {
	GPIO_DRV_WEAK			= 0,
	GPIO_DRV_WEAKER			= 1,
	GPIO_DRV_STRONGER		= 2,
	GPIO_DRV_STRONG			= 3,
};

#define T113_GPIOB2			(32 + 2)
#define T113_GPIOB3			(32 + 3)
#define T113_GPIOB4			(32 + 4)
#define T113_GPIOB5			(32 + 5)
#define T113_GPIOB6			(32 + 6)
#define T113_GPIOB7			(32 + 7)

#define T113_GPIOC2			(64 + 2)
#define T113_GPIOC3			(64 + 3)
#define T113_GPIOC4			(64 + 4)
#define T113_GPIOC5			(64 + 5)
#define T113_GPIOC6			(64 + 6)
#define T113_GPIOC7			(64 + 7)

#define T113_GPIOD0			(96 + 0)
#define T113_GPIOD1			(96 + 1)
#define T113_GPIOD2			(96 + 2)
#define T113_GPIOD3			(96 + 3)
#define T113_GPIOD4			(96 + 4)
#define T113_GPIOD5			(96 + 5)
#define T113_GPIOD6			(96 + 6)
#define T113_GPIOD7			(96 + 7)
#define T113_GPIOD8			(96 + 8)
#define T113_GPIOD9			(96 + 9)
#define T113_GPIOD10		(96 + 10)
#define T113_GPIOD11		(96 + 11)
#define T113_GPIOD12		(96 + 12)
#define T113_GPIOD13		(96 + 13)
#define T113_GPIOD14		(96 + 14)
#define T113_GPIOD15		(96 + 15)
#define T113_GPIOD16		(96 + 16)
#define T113_GPIOD17		(96 + 17)
#define T113_GPIOD18		(96 + 18)
#define T113_GPIOD19		(96 + 19)
#define T113_GPIOD20		(96 + 20)
#define T113_GPIOD21		(96 + 21)
#define T113_GPIOD22		(96 + 22)

#define T113_GPIOE0			(128 + 0)
#define T113_GPIOE1			(128 + 1)
#define T113_GPIOE2			(128 + 2)
#define T113_GPIOE3			(128 + 3)
#define T113_GPIOE4			(128 + 4)
#define T113_GPIOE5			(128 + 5)
#define T113_GPIOE6			(128 + 6)
#define T113_GPIOE7			(128 + 7)
#define T113_GPIOE8			(128 + 8)
#define T113_GPIOE9			(128 + 9)
#define T113_GPIOE10		(128 + 10)
#define T113_GPIOE11		(128 + 11)
#define T113_GPIOE12		(128 + 12)
#define T113_GPIOE13		(128 + 13)

#define T113_GPIOF0			(160 + 0)
#define T113_GPIOF1			(160 + 1)
#define T113_GPIOF2			(160 + 2)
#define T113_GPIOF3			(160 + 3)
#define T113_GPIOF4			(160 + 4)
#define T113_GPIOF5			(160 + 5)
#define T113_GPIOF6			(160 + 6)

#define T113_GPIOG0			(192 + 0)
#define T113_GPIOG1			(192 + 1)
#define T113_GPIOG2			(192 + 2)
#define T113_GPIOG3			(192 + 3)
#define T113_GPIOG4			(192 + 4)
#define T113_GPIOG5			(192 + 5)
#define T113_GPIOG6			(192 + 6)
#define T113_GPIOG7			(192 + 7)
#define T113_GPIOG8			(192 + 8)
#define T113_GPIOG9			(192 + 9)
#define T113_GPIOG10		(192 + 10)
#define T113_GPIOG11		(192 + 11)
#define T113_GPIOG12		(192 + 12)
#define T113_GPIOG13		(192 + 13)
#define T113_GPIOG14		(192 + 14)
#define T113_GPIOG15		(192 + 15)
/* IO pin */
enum gpio_pin
{
    GPIO_PIN_0 = 0,
    GPIO_PIN_1,
    GPIO_PIN_2,
    GPIO_PIN_3,
    GPIO_PIN_4,
    GPIO_PIN_5,
    GPIO_PIN_6,
    GPIO_PIN_7,
    GPIO_PIN_8,
    GPIO_PIN_9,
    GPIO_PIN_10,
    GPIO_PIN_11,
    GPIO_PIN_12,
    GPIO_PIN_13,
    GPIO_PIN_14,
    GPIO_PIN_15,
    GPIO_PIN_16,
    GPIO_PIN_17,
    GPIO_PIN_18,
    GPIO_PIN_19,
    GPIO_PIN_20,
    GPIO_PIN_21,
    GPIO_PIN_22,
    GPIO_PIN_23,
    GPIO_PIN_24,
    GPIO_PIN_NUM,
};

/* Drive level */
enum gpio_drv_level
{
    DRV_LEVEL_0 = 0,
    DRV_LEVEL_1,
    DRV_LEVEL_2,
    DRV_LEVEL_3,
};

/* Pull mode */
enum gpio_pull
{
    PULL_DISABLE = 0,
    PULL_UP,
    PULL_DOWN,
};

enum gpio_pull_t {
	GPIO_PULL_UP   = 0,
	GPIO_PULL_DOWN = 1,
	GPIO_PULL_NONE = 2,
};

/* interrupt type */
enum gpio_irq_type
{
    POSITIVE = 0,
    NEGATIVE,
    HIGH,
    LOW,
    DOUBLE,
};

enum gpio_debounce_clock
{
    GPIO_IRQ_LOSC_32KHZ = 0,
    GPIO_IRQ_HOSC_24MHZ
};

enum gpio_debounce_prescale
{
    DEBOUNCE_PRE_SCALE_1 = 0,
    DEBOUNCE_PRE_SCALE_2,
    DEBOUNCE_PRE_SCALE_4,
    DEBOUNCE_PRE_SCALE_8,
    DEBOUNCE_PRE_SCALE_16,
    DEBOUNCE_PRE_SCALE_32,
    DEBOUNCE_PRE_SCALE_64,
    DEBOUNCE_PRE_SCALE_128,
};

struct gpio_irq_def
{
    void    *irq_arg[32];
    void (*irq_cb[32])(void *param);
};

#define GPIO_BASE_ADDR           (0x02000000)
#define GPIOn_CFG_ADDR(n)        (GPIO_BASE_ADDR + (n) * 0x30 + 0x00)
#define GPIOn_DATA_ADDR(n)       (GPIO_BASE_ADDR + (n) * 0x30 + 0x10)
#define GPIOn_DRV_ADDR(n)        (GPIO_BASE_ADDR + (n) * 0x30 + 0x14)
#define GPIOn_PUL_ADDR(n)        (GPIO_BASE_ADDR + (n) * 0x30 + 0x24)
#define GPIOn_INT_CFG_ADDR(n)    (GPIO_BASE_ADDR + 0x200 + (n) * 0x20 + 0x00)
#define GPIOn_INT_CTRL_ADDR(n)   (GPIO_BASE_ADDR + 0x200 + (n) * 0x20 + 0x10)
#define GPIOn_INT_STA_ADDR(n)    (GPIO_BASE_ADDR + 0x200 + (n) * 0x20 + 0x14)
#define GPIOn_INT_DEB_ADDR(n)    (GPIO_BASE_ADDR + 0x200 + (n) * 0x20 + 0x18)



struct sunxi_gpio
{
    volatile rt_uint32_t reserved0[9];
    volatile rt_uint32_t pb_cfg0;        /* 0x24 */
    volatile rt_uint32_t pb_cfg1;        /* 0x28 */
    volatile rt_uint32_t pb_cfg2;        /* 0x2C */
    volatile rt_uint32_t pb_cfg3;        /* 0x30 */
    volatile rt_uint32_t pb_data;        /* 0x34 */
    volatile rt_uint32_t pb_drv0;        /* 0x38 */
    volatile rt_uint32_t pb_drv1;        /* 0x3C */
    volatile rt_uint32_t pb_pul0;        /* 0x40 */
    volatile rt_uint32_t pb_pul1;        /* 0x44 */
    volatile rt_uint32_t pc_cfg0;        /* 0x48 */
    volatile rt_uint32_t pc_cfg1;        /* 0x4C */
    volatile rt_uint32_t pc_cfg2;        /* 0x50 */
    volatile rt_uint32_t pc_cfg3;        /* 0x54 */
    volatile rt_uint32_t pc_data;        /* 0x58 */
    volatile rt_uint32_t pc_drv0;        /* 0x5C */
    volatile rt_uint32_t pc_drv1;        /* 0x60 */
    volatile rt_uint32_t pc_pul0;        /* 0x64 */
    volatile rt_uint32_t pc_pul1;        /* 0x68 */
#if defined(BSP_CHIP_V3S)
    volatile rt_uint32_t reserved1[9];   /* 0x6C */
#elif defined(BSP_CHIP_R11)
    volatile rt_uint32_t pd_cfg0;        /* 0x6C */
    volatile rt_uint32_t pd_cfg1;        /* 0x70 */
    volatile rt_uint32_t pd_cfg2;        /* 0x74 */
    volatile rt_uint32_t pd_cfg3;        /* 0x78 */
    volatile rt_uint32_t pd_data;        /* 0x7C */
    volatile rt_uint32_t pd_drv0;        /* 0x80 */
    volatile rt_uint32_t pd_drv1;        /* 0x84 */
    volatile rt_uint32_t pd_pul0;        /* 0x88 */
    volatile rt_uint32_t pd_pul1;        /* 0x8C */
#endif
    volatile rt_uint32_t pe_cfg0;        /* 0x90 */
    volatile rt_uint32_t pe_cfg1;        /* 0x94 */
    volatile rt_uint32_t pe_cfg2;        /* 0x98 */
    volatile rt_uint32_t pe_cfg3;        /* 0x9C */
    volatile rt_uint32_t pe_data;        /* 0xA0 */
    volatile rt_uint32_t pe_drv0;        /* 0xA4 */
    volatile rt_uint32_t pe_drv1;        /* 0xA8 */
    volatile rt_uint32_t pe_pul0;        /* 0xAC */
    volatile rt_uint32_t pe_pul1;        /* 0xB0 */
    volatile rt_uint32_t pf_cfg0;        /* 0xB4 */
    volatile rt_uint32_t pf_cfg1;        /* 0xB8 */
    volatile rt_uint32_t pf_cfg2;        /* 0xBC */
    volatile rt_uint32_t pf_cfg3;        /* 0xC0 */
    volatile rt_uint32_t pf_data;        /* 0xC4 */
    volatile rt_uint32_t pf_drv0;        /* 0xC8 */
    volatile rt_uint32_t pf_drv1;        /* 0xCC */
    volatile rt_uint32_t pf_pul0;        /* 0xD0 */
    volatile rt_uint32_t pg_cfg0;        /* 0xD8 */
    volatile rt_uint32_t pg_cfg1;        /* 0xDC */
    volatile rt_uint32_t pg_cfg2;        /* 0xE0 */
    volatile rt_uint32_t pg_cfg3;        /* 0xE4 */
    volatile rt_uint32_t pg_data;        /* 0xE8 */
    volatile rt_uint32_t pg_drv0;        /* 0xEC */
    volatile rt_uint32_t pg_drv1;        /* 0xF0 */
    volatile rt_uint32_t pg_pul0;        /* 0xF4 */
    volatile rt_uint32_t pg_pul1;        /* 0xF8 */
    volatile rt_uint32_t reserved2[73];
    volatile rt_uint32_t pb_int_cfg0;    /* 0x220 */
    volatile rt_uint32_t pb_int_cfg1;    /* 0x224 */
    volatile rt_uint32_t pb_int_cfg2;    /* 0x228 */
    volatile rt_uint32_t pb_int_cfg3;    /* 0x22C */
    volatile rt_uint32_t pb_int_ctrl;    /* 0x230 */
    volatile rt_uint32_t pb_int_sta;     /* 0x234 */
    volatile rt_uint32_t pb_int_deb;     /* 0x238 */
    volatile rt_uint32_t reserved3;
    volatile rt_uint32_t pg_int_cfg0;    /* 0x240 */
    volatile rt_uint32_t pg_int_cfg1;    /* 0x244 */
    volatile rt_uint32_t pg_int_cfg2;    /* 0x248 */
    volatile rt_uint32_t pg_int_cfg3;    /* 0x24C */
    volatile rt_uint32_t pg_int_ctrl;    /* 0x250 */
    volatile rt_uint32_t pg_int_sta;     /* 0x254 */
    volatile rt_uint32_t pg_int_deb;     /* 0x258 */
};

typedef struct sunxi_gpio *sunxi_gpio_t;

#define GPIO ((sunxi_gpio_t)GPIO_BASE_ADDR)

int gpio_set_func(enum gpio_port port, enum gpio_pin pin, rt_uint8_t func);
int gpio_set_value(enum gpio_port port, enum gpio_pin pin, rt_uint8_t value);
int gpio_get_value(enum gpio_port port, enum gpio_pin pin);
int gpio_set_pull_mode(enum gpio_port port, enum gpio_pin pin, enum gpio_pull pull);
int gpio_set_drive_level(enum gpio_port port, enum gpio_pin pin, enum gpio_drv_level level);
void gpio_direction_input(enum gpio_port port, enum gpio_pin pin);
void gpio_direction_output(enum gpio_port port, enum gpio_pin pin, int value);

void gpio_irq_set_type(enum gpio_port port, enum gpio_pin pin, enum gpio_irq_type irq_type);
void gpio_irq_enable(enum gpio_port port, enum gpio_pin pin);
void gpio_irq_disable(enum gpio_port port, enum gpio_pin pin);
void gpio_irq_clear(enum gpio_port port, enum gpio_pin pin);

void gpio_irq_set_callback(enum gpio_port port, enum gpio_pin pin, void (*irq_cb)(void *), void *irq_arg);
void gpio_irq_clear_callback(enum gpio_port port, enum gpio_pin pin);

void gpio_set_debounce(enum gpio_port port, enum gpio_debounce_clock clock, enum gpio_debounce_prescale prescale);

int rt_hw_gpio_init(void);

void gpio_t113_set_value(int offset, int value);
void gpio_t113_set_dir(int offset, int dir);
void gpio_t113_set_drv(int offset, enum gpio_drv_t drv);


typedef uint32_t gpio_t;
#define PIO_NUM_IO_BITS 5
enum {
	GPIO_INPUT		  = 0,
	GPIO_OUTPUT		  = 1,
	GPIO_PERIPH_MUX2  = 2,
	GPIO_PERIPH_MUX3  = 3,
	GPIO_PERIPH_MUX4  = 4,
	GPIO_PERIPH_MUX5  = 5,
	GPIO_PERIPH_MUX6  = 6,
	GPIO_PERIPH_MUX7  = 7,
	GPIO_PERIPH_MUX8  = 8,
	GPIO_PERIPH_MUX14 = 14,
	GPIO_DISABLED	  = 0xf,
};

#define PORTB			 0
#define PORTC			 1
#define PORTD			 2
#define PORTE			 3
#define PORTF			 4
#define PORTG			 5
#define SUNXI_GPIO_PORTS (PORTG + 1)
#define GPIO_PIN(x, y) (((uint32_t)(x << PIO_NUM_IO_BITS)) | y)

typedef struct {
	gpio_t	pin;
	uint8_t mux;
} gpio_mux_t;

extern void sunxi_gpio_init(gpio_t pin, int cfg);
extern void sunxi_gpio_set_value(gpio_t pin, int value);
extern int	sunxi_gpio_read(gpio_t pin);
extern void sunxi_gpio_set_pull(gpio_t pin, enum gpio_pull_t pull);

#endif /* __DRV_GPIO_H__ */
